<?php
/**
 * Created by PhpStorm.
 * User: allen_ios
 * Date: 17/2/20
 * Time: 下午7:22
 */
namespace Task\Core;
use Task\Core\Base;
class WechatApi {
    public $expires_in = 7200;			//access_token有效期
    public $delay_time = 60;				//access_token有效期误差补平
    public $account_id;
    public $token;
    public $appid;
    public $appsecret;
    public $access_token;
    public $wechat;
    public $mysql;

    /**
     * 初始化
     */
    public function __construct($wechat, $account_id, $appsecret=''){
        $this->account_id = $account_id;

        $this->mysql=Database::getInstance('mysql');
        if(!$wechat['wechat_id']){
            return array('status' => 'F', 'message' => 'wechat_id不能为空');
        }

        $this->wechat = $wechat;

        if(!$this->wechat){
            return array('status' => 'F', 'message' => '公众号信息不存在');
        }
        $this->token = $this->wechat['token'];
        $this->appid = $this->wechat['appid'];
        $this->appsecret = $appsecret ? $appsecret : $this->wechat['appsecret'];
        $result = $this->getAccessToken();


        if($result['status'] != 'S'){
            return $result;
        }else{
            $this->access_token = $result['message'];
        }
    }



    /**
     * 微信Api调用公用返回
     */
    public function apiReturn($result, $parameter = array()){
        if(!$result){
            $status = 'F';
            $message = 'php环境未开启ssl等原因';
        }else if($result['errcode'] && is_array($result) && ($result['errcode'] != 'ok')){
            //access_token失效刷新重置
            if(($result['errcode'] == '40001') && !empty($parameter) && !session('access_token_refresh') ){
                //强制刷新access_token
                $this->getAccessToken(true);
                session('access_token_refresh', true);
                $method = $parameter[0];
                unset($parameter[0]);
                $return = call_user_func_array(array('Wechat_api', $method), $parameter);
                return $this->apiReturn($return);
            }else{
                $status = 'F';
                $message = $result['errcode'].$result['errmsg'];
            }
        }else{
            $status = 'S';
            $message = $result;
        }
        return array('status' => $status, 'message' => $message);
    }

    /**
     * 获取全局Access_token
     */
    public function getAccessToken($refresh = false){
        if($refresh || !$this->wechat['access_token'] || ($this->wechat['access_token_update_time']<=(time()+$this->delay_time-$this->expires_in))){
            // access_token已失效
            $url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->appid.'&secret='.$this->appsecret;
//			$result = Http::curlGet($url);
//			wLog('getAccessToken:'.var_export($result,true),'getAccessToken');die;

//			$curl = new Http();
            $result = json_decode(file_get_contents($url),true);
            if($result['errcode']){
                $status = 'F';
                $message = $result['errcode'].$result['errmsg'];
            }else{
                $status = 'S';
                $message = $result['access_token'];

                $sql = "update gc_wechat set access_token='".$message."',access_token_update_time=".time()." where wechat_id=".$this->wechat['wechat_id'];
                $res = $this->mysql->exec($sql);
            }
        }else{
            $status = 'S';
            $message = $this->wechat['access_token'];
        }
        $this->access_token = $message;
        //验证access_token有效性
// 		$verify = $this->getIp();
        if(in_array($verify['errcode'], array(40001, 42001)) && !session('?update_access_token')){

            $sql2 = "update gc_wechat set access_token='".$message."',access_token_update_time='' where wechat_id=".$this->wechat['wechat_id'];
            session('update_access_token', 1);
            $res2 = $this->mysql->exec($sql);
            $this->getAccessToken();
        }
        return array('status' => $status, 'message' => $message);
    }

    /**
     * 获取微信服务器ip
     */
    public function getIp(){
        $url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token='.$this->access_token;
        $result = json_decode(file_get_contents($url), true);
        // 接口调用存储
        $this->apiCallSave('getIp', 'wechat', $url, json_encode($result), $result['errcode']);
        return $result;
    }

    /**
     * 获取jsapi_ticket
     */
    public function getJsapi_ticket(){
        if($this->wechat['ticket_update_time']>(time()+$this->delay_time-$this->expires_in)){
            // jsapi_ticket未过期
            $ticket=$this->wechat['jsapi_ticket'];
            $noncestr=$this->wechat['jsapi_noncestr'];
            $time=$this->wechat['ticket_update_time'];
            $status='S';
        }else{
            $url='https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$this->access_token.'&type=jsapi';
            $result=json_decode(file_get_contents($url),true);
            if($result['errcode']){
                $status='F';
                $message=$result['errcode'].$result['errmsg'];
            }else{
                $status='S';
                $ticket=$result['ticket'];
                $noncestr=$this->createNoncestr(16);
                $time=time();
                // 存储jsapi_ticket
                M('wechat')->where(array('wechat_id'=>$this->wechat['wechat_id']))->save(array('jsapi_ticket'=>$ticket,'jsapi_noncestr'=>$noncestr,'ticket_update_time'=>$time));
            }
            // 接口调用存储
            $this->apiCallSave('getJsapi_ticket', 'wechat', $url, json_encode($result),$result['errcode']);
        }
        if($status=='S'){
            // 生成签名
            $string='jsapi_ticket='.$ticket.'&noncestr='.$noncestr.'&timestamp='.$time.'&url=http://'.$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI];
            $signature=sha1($string);
            $message=array('signature'=>$signature,'noncestr'=>$noncestr,'timestamp'=>$time);
        }
        return array('status'=>$status,'message'=>$message);
    }

    /**
     * 产生随机字符串，不长于32位
     */
    public function createNoncestr($length =16){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for($i=0;$i< $length;$i++){
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     * 微信消息模板
     * 参数里面有中文的请在调用该函数前对中文进行urlencode处理
     */
    public function messageTpl($Appid, $Appsecret, $openid, $template_id, $data, $url='', $topcolor='#FF0000'){
        $result = $this->getAccessToken($Appid, $Appsecret);



        if($result['status'] != 'S'){
            return $result; exit;
        }
        $access_token = $result['message'];



        $post_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$access_token";
        $array = array(
            'touser' => $openid,
            'template_id' => $template_id,
            'url' => $url,
            'topcolor' => $topcolor,
            'data' => $data,
        );
        $json = urldecode(json_encode($array));
        $result = $this->curl_post_info($post_url, $json);
        // 接口调用存储
        $parameter = array('messageTpl', $openid, $template_id, $data, $url, $topcolor);
        return $this->apiReturn($result, $parameter);
    }


    /**
     * Curl向特定url post数据
     */
    public function curl_post_info($url, $data){
        $ch = curl_init();
        $header = "Accept-Charset: utf-8";
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $tmpInfo = json_decode(curl_exec($ch),true);
        if (curl_errno($ch)) {
            return false;
        }else{
            return $tmpInfo;
        }
        curl_close($ch);
    }


    /**
     * 获取用户基本信息(UnionID机制)
     */
    public function getFansInfo($openid){
        $url='https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$this->access_token.'&openid='.$openid.'&lang=zh_CN';
        //消除8进制对json_decode的影响，（尚未解决）
// 		$result = str_replace("NN=", '', file_get_contents($url));
        $result = file_get_contents($url);
        $result = json_decode($result, true);
        //接口调用存储
        $parameter = array('getFansInfo', $openid);
        $this->apiCallSave('getFansInfo', $openid, $url, json_encode($result), $result['errcode']);
        return $this->apiReturn($result, $parameter);
    }

    /**
     * 通过OAuth 2.0工具获取用户基本信息
     */
    public function getFansInfoOauth($code){
        if(!$code){
            return array('status'=>'F','message'=>'code为空');
        }
        // 获取openid
        $url='https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code';
        $array=json_decode(file_get_contents($url),true);
        if($array['errcode']){
            return array('status'=>'F','message'=>$array['errcode'].$array['errmsg']);
        }
        $openid=$array['openid'];
        $oauth_access_token=$array['access_token'];
        // 获取用户信息
        $url='https://api.weixin.qq.com/sns/userinfo?access_token='.$oauth_access_token.'&openid='.$openid.'&lang=zh_CN';
        $result=json_decode(file_get_contents($url),true);
        // 接口调用存储
        $parameter = array('getFansInfoOauth', $code);
        $this->apiCallSave('getFansInfoOauth', $openid, $url, json_encode($result),$result['errcode']);
        return $this->apiReturn($result, $parameter);
    }

    /**
     * 获取用户列表
     */
    public function getFansList($nextOpenid='', $loop=true){
        $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='.$this->access_token;
        if($nextOpenid){
            $url .= '&next_openid='.$nextOpenid;
        }
        $result = json_decode(file_get_contents($url), true);
        // 数据超出10000
        if(($result['count'] == 10000) && ($result['total'] > 10000) && $loop){
            $next = $this->getFansList($result['next_openid'], true);
            if($next['status'] == 'S'){
                $result['data']['openid'] = array_merge($result['data']['openid'], $next['message']['data']['openid']);
                $result['count'] += $next['message']['count'];
            }else{
                return $next;
            }
        }
        //接口调用存储
        $parameter = array('getFansList', $nextOpenid, $loop);
        $this->apiCallSave('getFansList', 'wechat', $url, json_encode($result), $result['errcode']);
        return $this->apiReturn($result, $parameter);
    }


}